import platform
import time
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta

from app.enums.enums import RoleEnum
from app.util.log_utils import add_log_event, get_logs
import psutil
from sqlalchemy import func
from app import db, redis_client, file_handler, app
import logging
from app.models import User, House
import os

# 配置日志记录器
logger = logging.getLogger(__name__)


def get_total_disk_usage():
    """
    获取windows下系统磁盘使用情况
    :return: 总大小，使用大小
    """
    # 获取所有逻辑驱动器
    partitions = psutil.disk_partitions(all=False)
    drives = [p.device for p in partitions if 'cdrom' not in p.opts and p.fstype]

    if not drives:
        logger.error("未发现可访问的逻辑驱动器")
        add_log_event("获取系统磁盘使用情况有误", "未发现可访问的逻辑驱动器")
        return None, None

    # 计算总容量和已使用空间
    total_capacity = 0
    total_used = 0

    for drive in drives:
        try:
            usage = psutil.disk_usage(drive)
            total_capacity += usage.total
            total_used += usage.used
        except PermissionError:
            logger.error(f"× 无法访问驱动器 {drive} 的使用情况（权限不足）")
            add_log_event("获取系统磁盘使用情况有误", f"无法访问驱动器 {drive} 的使用情况（权限不足）")
        except Exception as e:
            logger.error(f"× 获取驱动器 {drive} 信息时出错: {e}")
            add_log_event("获取系统磁盘使用情况有误", f"获取驱动器 {drive} 信息时出错: {e}")

    # 计算总体使用率
    if total_capacity > 0:
        total_capacity_gb = total_capacity / (1024 ** 3)
        total_used_gb = total_used / (1024 ** 3)

        return total_capacity_gb, total_used_gb
    else:
        print("\n无法计算总磁盘使用率")
        add_log_event("获取系统磁盘使用情况有误", "无法计算总磁盘使用率")
        return None, None


def get_file_info(folder_path):
    """
    获取目录下的文件名和大小
    :param folder_path: 文件夹
    :return:
    """
    file_info_list = []
    # 遍历文件夹中的所有条目
    for entry in os.scandir(folder_path):
        if entry.is_file():  # 过滤出文件（非文件夹）
            # 获取文件名和大小（字节）
            filename = entry.name
            file_size = entry.stat().st_size
            file_info_list.append({
                "filename": filename,
                "size": file_size
            })
    return file_info_list


class MonitorService:

    # @staticmethod
    # def get_system_base_information(user_id):
    #     """
    #     获取系统的基本信息
    #     :param user_id: 用户id
    #     :return: success,message,data
    #     """
    #     logger.info("管理员" + str(user_id) + "查询系统基本信息")
    #     try:
    #         # 获取系统运行时间
    #         start_time = redis_client.hget("systemInfo", "start_time")
    #         run_time = (time.time() - float(start_time))
    #         # 计算小时数（整除 3600，因为 1小时=3600秒）
    #         hours = run_time // 3600
    #         # 计算剩余秒数（总秒数减去小时对应的秒数）
    #         remaining_seconds = run_time % 3600
    #         # 计算分钟数（剩余秒数整除 60，因为 1分钟=60秒）
    #         minutes = remaining_seconds // 60
    #
    #         # 获取房屋数和今日新增的房屋数
    #         # 获取今天的日期（本地时间）
    #         today = datetime.now().date()
    #         # 计算昨天的日期
    #         yesterday = today - timedelta(days=1)
    #         house_count = House.query.count()
    #         raise_count = House.query.filter(
    #             func.date(House.create_time) == today
    #         ).count()
    #         # 获取活跃用户数（两天）
    #         active_user_today = len(redis_client.smembers("active_ip:" + str(today)))
    #         active_user_yesterday = len(redis_client.smembers("active_ip:" + str(yesterday)))
    #         # 获取系统告警消息数
    #         warning_count = 0
    #         logs = get_logs()
    #         for log in logs:
    #             if log["level"] == "error" or log["level"] == "warning":
    #                 warning_count += 1
    #         # 获取系统cpu、内存占有、磁盘占有
    #         # 获取 CPU 整体使用率（采样 0.1 秒）
    #         cpu_percent = psutil.cpu_percent(interval=0.1)
    #         # 获取内存信息
    #         memory = psutil.virtual_memory()
    #         # 转换为 GB 单位
    #         total_gb = memory.total / (1024 ** 3)
    #         used_gb = memory.used / (1024 ** 3)
    #         # 获取当前系统
    #         os_name = platform.system()
    #         if os_name == 'Windows':
    #             total_disk_gb, used_disk_gb = get_total_disk_usage()
    #         else:
    #             disk = psutil.disk_usage('/')
    #             total_disk_gb = disk.total / (1024 ** 3)
    #             used_disk_gb = disk.used / (1024 ** 3)
    #         log_remain_days = redis_client.get('log_remain_days')
    #         if not log_remain_days:
    #             log_remain_days = 30
    #         else:
    #             log_remain_days = int(log_remain_days)
    #         return True, "", {
    #             'log_remain_days': log_remain_days,
    #             "run_time": {
    #                 "hours": hours,
    #                 "minutes": minutes,
    #             },
    #             "house": {
    #                 "house_count": house_count,
    #                 "raise_count": raise_count,
    #             },
    #             "active_user": {
    #                 "today": active_user_today,
    #                 "yesterday": active_user_yesterday,
    #             },
    #             "warning_count": warning_count,
    #             "system": {
    #                 "cpu_percent": cpu_percent,
    #                 "total_gb": int(total_gb),
    #                 "used_gb": int(used_gb),
    #                 "total_disk_gb": int(total_disk_gb),
    #                 "used_disk_gb": int(used_disk_gb),
    #             }
    #         }
    #     except Exception as e:
    #         logger.error(e)
    #         return False, "获取系统概述失败", None

    @staticmethod
    def get_system_base_information(user_id):
        """
        获取系统的基本信息
        :param user_id: 用户id
        :return: success,message,data
        """
        logger.info("管理员" + str(user_id) + "查询系统基本信息")

        def get_run_time():
            try:
                start_time = redis_client.hget("systemInfo", "start_time")
                run_time = (time.time() - float(start_time))
                hours = run_time // 3600
                remaining_seconds = run_time % 3600
                minutes = remaining_seconds // 60
                return {
                    "hours": hours,
                    "minutes": minutes,
                }
            except Exception as e:
                logger.error(f"获取运行时间失败: {e}")
                raise Exception(e)

        def get_house_info():
            try:
                with app.app_context():
                    today = datetime.now().date()
                    house_count = House.query.count()
                    raise_count = House.query.filter(
                        func.date(House.create_time) == today
                    ).count()
                    return {
                        "house_count": house_count,
                        "raise_count": raise_count,
                    }
            except Exception as e:
                logger.error(f"获取房屋信息失败: {e}")
                raise Exception(e)

        def get_active_users():
            try:
                today = datetime.now().date()
                yesterday = today - timedelta(days=1)
                active_user_today = len(redis_client.smembers("active_ip:" + str(today)))
                active_user_yesterday = len(redis_client.smembers("active_ip:" + str(yesterday)))
                return {
                    "today": active_user_today,
                    "yesterday": active_user_yesterday,
                }
            except Exception as e:
                logger.error(f"获取活跃用户失败: {e}")
                raise Exception(e)

        def get_warning_count():
            try:
                warning_count = 0
                logs = get_logs()
                for log in logs:
                    if log["level"] == "error" or log["level"] == "warning":
                        warning_count += 1
                return warning_count
            except Exception as e:
                logger.error(f"获取告警数量失败: {e}")
                raise Exception(e)

        def get_system_resources():
            try:
                cpu_percent = psutil.cpu_percent(interval=0.1)
                memory = psutil.virtual_memory()
                total_gb = memory.total / (1024 ** 3)
                used_gb = memory.used / (1024 ** 3)
                os_name = platform.system()
                if os_name == 'Windows':
                    total_disk_gb, used_disk_gb = get_total_disk_usage()
                else:
                    disk = psutil.disk_usage('/')
                    total_disk_gb = disk.total / (1024 ** 3)
                    used_disk_gb = disk.used / (1024 ** 3)
                return {
                    "cpu_percent": cpu_percent,
                    "total_gb": int(total_gb),
                    "used_gb": int(used_gb),
                    "total_disk_gb": int(total_disk_gb),
                    "used_disk_gb": int(used_disk_gb),
                }
            except Exception as e:
                logger.error(f"获取系统资源失败: {e}")
                raise Exception(e)

        def get_log_remain_days():
            try:
                log_remain_days = redis_client.get('log_remain_days')
                return int(log_remain_days) if log_remain_days else 30
            except Exception as e:
                logger.error(f"获取日志保留天数失败: {e}")
                return 30

        try:
            with ThreadPoolExecutor(max_workers=6) as executor:
                future_run_time = executor.submit(get_run_time)
                future_house = executor.submit(get_house_info)
                future_active = executor.submit(get_active_users)
                future_warning = executor.submit(get_warning_count)
                future_system = executor.submit(get_system_resources)
                future_log = executor.submit(get_log_remain_days)

            return True, "", {
                'log_remain_days': future_log.result(),
                "run_time": future_run_time.result(),
                "house": future_house.result(),
                "active_user": future_active.result(),
                "warning_count": future_warning.result(),
                "system": future_system.result(),
            }
        except Exception as e:
            logger.error(f"获取系统概述失败: {e}")
            return False, "获取系统概述失败", None

    @staticmethod
    def get_system_logs(user_id):
        """
        获取系统关键日志
        :param user_id: 用户id
        :return: success,message,data
        """
        logger.info("管理员" + str(user_id) + "查询系统关键日志")
        try:
            logs = get_logs()
            return True, "", logs
        except Exception as e:
            logger.error(e)
            return False, "获取日志失败", None

    @staticmethod
    def change_logs_remain_days(user_id, days):
        """
        修改日志保留天数
        :param user_id: 用户id
        :return: success,message
        """
        logger.info("管理员" + str(user_id) + "执行修改日志保留天数操作")
        file_handler.backupCount = days
        redis_client.set("log_remain_days", days)
        return True, ""

    @staticmethod
    def get_interfaces(user_id):
        """
        获取接口信息
        :param user_id: 用户id
        :return: success,message,data
        """
        logger.info("管理员" + str(user_id) + "执行获取接口信息操作")
        try:
            # 获取请求次数
            ic = redis_client.hgetall("interface_counts")
            ic = {key: int(value) for key, value in ic.items()}
            # 获取请求正确次数（非系统错误的响应）
            irc = redis_client.hgetall("interface_right_counts")
            irc = {key: int(value) for key, value in irc.items()}
            # 获取请求总时间
            times = redis_client.hgetall("interface_times")
            times = {key: int(value) for key, value in times.items()}
            # 获取最后请求时间
            last_times = redis_client.hgetall('interface_last_times')
            last_times = {key: int(value) for key, value in last_times.items()}
            # 构建返回值
            all_counts = sum(ic.values())
            all_right_counts = sum(irc.values())
            interfaces = []
            for key, value in ic.items():
                data = {
                    "path": key,
                    "total_count": value,
                    "fail_count": value - irc.get(key, 0),
                    "avg_time": round(times.get(key, 0) / value, 2),
                    "last_time": last_times.get(key, 0),
                }
                interfaces.append(data)
            logger.info("获取接口信息成功")
            return True, "", {
                "all_counts": all_counts,
                "all_right_counts": all_right_counts,
                "right_percent": round((all_right_counts / all_counts * 100), 2),
                "interfaces": interfaces
            }
        except Exception as e:
            logger.error("获取接口信息失败：" + str(e))
            return False, "获取接口信息失败", None

    @staticmethod
    def get_log_file(user_id):
        """
        获取日志元信息
        :param user_id: 用户id
        :return: success,message,data
        """
        logger.info("管理员" + str(user_id) + "获取日志文件信息")
        try:
            file_info = get_file_info('logs')
            logger.info("获取日志文件元信息成功：" + str(file_info))
            return True, "", file_info
        except Exception as e:
            logger.error(e)
            return False, "获取日志文件信息失败", None
